package com.uinnova.product.eam.service.impl;

import com.binary.jdbc.Page;
import com.uinnova.product.eam.comm.bean.Resolution;
import com.uinnova.product.eam.comm.bean.ResolutionDoc;
import com.uinnova.product.eam.model.ResolutionCdt;
import com.uinnova.product.eam.service.IEamResolutionSvc;
import com.uinnova.product.eam.service.es.IamsEsResolutionDocSvc;
import com.uinnova.product.eam.service.es.IamsEsResolutionSvc;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import com.uino.service.sys.microservice.IResourceSvc;
import com.uino.util.rsm.RsmUtils;
import com.uino.util.sys.SysUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 架构决议接口实现类
 *
 * @author lichong
 */
@Service
public class IamsEamResolutionSvcImpl implements IEamResolutionSvc {

    private static final Logger log = LoggerFactory.getLogger(IamsEamResolutionSvcImpl.class);

    @Autowired
    private IamsEsResolutionSvc iamsEsResolutionSvc;

    @Autowired
    private IamsEsResolutionDocSvc iamsEsResolutionDocSvc;

    @Value("${local.resource.space}")
    private String localPath;

    @Autowired
    private IResourceSvc resourceSvc;

    @Value("${http.resource.space}")
    private String urlPath;

    @Autowired
    private IUserApiSvc userApiSvc;

    @Autowired
    private RsmUtils rsmUtils;

    /**
     * 文档合法性正则
     */
    @Value("${uino.eam.word_name_regex}")
    private String wordNameregex;

    @Override
    public Long addResolution(Resolution resolution, MultipartFile[] files) {
        Set<Map<String, Object>> docs = resolution.getDocs();

        long resolutionId = ESUtil.getUUID();
        for (MultipartFile file : files) {
            //保存文件到服务器
            Map<String, Object> map = saveFile(resolutionId, file);
            docs.add(map);
        }
        resolution.setId(resolutionId);
        resolution.setResolutionTime(new Date());
        resolution.setUpdateTime(new Date());
        return iamsEsResolutionSvc.saveOrUpdate(resolution);
    }

    @Override
    public void deleteResolutionDoc(Long resolutionId, Long resolutionDocId) {
        ResolutionDoc resolutionDoc = iamsEsResolutionDocSvc.getById(resolutionDocId);
        if (resolutionDoc != null) {
            if (resolutionDoc.getRealPath() != null) {
                // 删除服务器文件
                new File(resolutionDoc.getRealPath()).delete();
                rsmUtils.deleteRsm(resolutionDoc.getRealPath());
            }
            // 删除决议文档es索引数据
            iamsEsResolutionDocSvc.deleteById(resolutionDocId);
        }
        // 在决议中删除
        Resolution resolution = iamsEsResolutionSvc.getById(resolutionId);
        Set<Map<String, Object>> docs = resolution.getDocs();
        docs.removeIf(doc -> doc.containsValue(resolutionDocId));
        iamsEsResolutionSvc.saveOrUpdate(resolution);
    }

    @Override
    public Page<Resolution> searchResolutions(ResolutionCdt resolutionsCdt) {
        if (resolutionsCdt.getPageSize() == null || resolutionsCdt.getPageSize() > 20000) {
            resolutionsCdt.setPageSize(10);
        }
        if (resolutionsCdt.getPageNum() == null || resolutionsCdt.getPageNum() < 0) {
            resolutionsCdt.setPageNum(0);
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().
                must(QueryBuilders.termQuery("ciCode.keyword", resolutionsCdt.getCiCode()));
        Page<Resolution> resolutionPage;
        if (StringUtils.isBlank(resolutionsCdt.getSort())) {
            resolutionsCdt.setSort("resolutionTime");
        }
        if (!resolutionsCdt.getSort().endsWith("Time")) {
            resolutionsCdt.setSort(resolutionsCdt.getSort() + ".keyword");
        }
        resolutionPage = iamsEsResolutionSvc.getSortListByQuery(resolutionsCdt.getPageNum(),
                resolutionsCdt.getPageSize(), queryBuilder, resolutionsCdt.getSort(), resolutionsCdt.getAsc());
        HashSet<String> loginCodeList = new HashSet<>();
        for (Resolution resolution : resolutionPage.getData()) {
            for (Map<String, Object> doc : resolution.getDocs()) {
                String operator = (String) doc.get("operator");
                loginCodeList.add(operator);
            }
        }
        CSysUser cSysUser = new CSysUser();
        cSysUser.setLoginCodes(loginCodeList.toArray(new String[0]));
        List<SysUser> sysUserByCdt = userApiSvc.getSysUserByCdt(cSysUser);
        HashMap<String, String> conversionMap = new HashMap<>();
        for (SysUser sysUser : sysUserByCdt) {
            conversionMap.put(sysUser.getLoginCode(), sysUser.getUserName());
        }
        for (Resolution resolution : resolutionPage.getData()) {
            Set<Map<String, Object>> docs = resolution.getDocs();
            for (Map<String, Object> doc : docs) {
                String operator = String.valueOf(doc.get("operator"));
                doc.put("operator", conversionMap.get(operator));
            }
        }

        return resolutionPage;
    }

    @Override
    public Resolution getById(Long resolutionId) {
        return iamsEsResolutionSvc.getById(resolutionId);
    }

    @Override
    public ResolutionDoc getResolutionDocByResolutionDocId(Long resolutionDocId) {
        return iamsEsResolutionDocSvc.getById(resolutionDocId);
    }

    @Override
    public Set<Map<String, Object>> uploadResolutionDoc(Long resolutionId, MultipartFile[] files) {
        HashSet<Map<String, Object>> maps = new HashSet<>();
        for (MultipartFile file : files) {
            Map<String, Object> map = saveFile(resolutionId, file);
            maps.add(map);
        }
        Resolution resolution = iamsEsResolutionSvc.getById(resolutionId);
        resolution.getDocs().addAll(maps);
        iamsEsResolutionSvc.saveOrUpdate(resolution);
        return resolution.getDocs();
    }

    @Override
    public void editResolution(Resolution resolution) {
        iamsEsResolutionSvc.saveOrUpdate(resolution);
    }

    @Override
    public void deleteResolutionById(Long id) {
        Resolution resolution = this.getById(id);
        if (resolution != null) {
            Set<Map<String, Object>> docs = resolution.getDocs();
            //删除决议文档
            for (Map<String, Object> doc : docs) {
                Long resolutionDocId = (Long) doc.get("resolutionDocId");
                this.deleteResolutionDoc(id, resolutionDocId);
            }
            //删除决议
            iamsEsResolutionSvc.deleteById(id);
        }
    }

    @Override
    public void deleteResolutionByIds(Long[] ids) {
        for (Long id : ids) {
            deleteResolutionById(id);
        }
    }

    @Override
    public ResolutionDoc getResolutionDocById(Long resolutionDocId) {
        return iamsEsResolutionDocSvc.getById(resolutionDocId);
    }

    @Override
    public void batchEditResolution(Resolution[] resolutions) {
        iamsEsResolutionSvc.saveOrUpdateBatch(Arrays.asList(resolutions));
    }

    private Map<String, Object> saveFile(Long resolutionId, MultipartFile file) {
        Map<String, Object> map = new HashMap<>(2);
        Long dateTimeFolder = ESUtil.getNumberDate();
        File destFolder = new File(localPath + "/" + dateTimeFolder);
        if (!destFolder.exists()) {
            destFolder.mkdirs();
        }
        String docName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
        String fileType = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!(file.getOriginalFilename().matches(wordNameregex))) {
            throw new RuntimeException(docName + "文件格式不正确");
        }
        //文件名重复删除覆盖
        Resolution resolution = iamsEsResolutionSvc.getById(resolutionId);
        if (resolution != null) {
            Set<Map<String, Object>> docs = resolution.getDocs();
            Iterator<Map<String, Object>> iterator = docs.iterator();
            if (iterator.hasNext()) {
                Map<String, Object> doc = iterator.next();
                if (doc.get("docName") == docName && doc.get("docType") == fileType) {
                    long resolutionDocId = (long) map.get("resolutionDocId");
                    this.deleteResolutionDoc(resolutionId, resolutionDocId);
                    iterator.remove();
                }
            }
            iamsEsResolutionSvc.saveOrUpdate(resolution);
        }
        String destFileName = ESUtil.getUUID() + "." + fileType;
        File destFile = new File(destFolder, destFileName);
        String realpath = null;
        try {
            String wordPath = "/" + dateTimeFolder + "/" + destFileName;
            realpath = destFile.getCanonicalPath();
            file.transferTo(new File(destFile.getCanonicalPath()));
            realpath = destFile.getCanonicalPath();

            File realFile = new File(realpath);
            rsmUtils.uploadRsmFromFile(realFile);

            // 记录资源操作信息
            resourceSvc.saveSyncResourceInfo(wordPath, urlPath + wordPath, false, 0);
        } catch (IOException e) {
            log.error("保存文件异常", e);
        }
        //保存文件到决议文档索引
        ResolutionDoc resolutionDoc = new ResolutionDoc();
        long resolutionDocId = ESUtil.getUUID();
        resolutionDoc.setId(resolutionDocId);
        resolutionDoc.setName(docName);
        resolutionDoc.setRealPath(realpath);
        resolutionDoc.setResolutionId(resolutionId);
        iamsEsResolutionDocSvc.saveOrUpdate(resolutionDoc);
        map.put("docName", docName);
        map.put("resolutionDocId", resolutionDocId);
        map.put("docType", fileType);
        map.put("operator", SysUtil.getCurrentUserInfo().getLoginCode());
        return map;
    }
}
